// -*- Mode: Go; indent-tabs-mode: t -*-
//
// Copyright (C) 2018 IOTech Ltd
//
// SPDX-License-Identifier: Apache-2.0

package main

import (
	"fmt"
	"math/rand"
	"net/url"
	"time"

	mqtt "github.com/eclipse/paho.mqtt.golang"
)

const (
	//brokerUrl  = "127.0.0.1"
	brokerUrl  = "192.168.0.248"
	brokerPort = 1883
	username   = "admin"
	password   = "public"
	frameLen   = 6 + 8 + 3000*2
)

// var topicSettings string = "edgex/event/mcu/settings"
// var topicRealtime string = "edgex/event/mcu/realtime"
// var topicSpindles string = "edgex/event/mcu/spindles"
// var topicCommand string = "edgex/event/mcu/command"
var topicVoltages string = "edgex/event/mcu/voltages"

func main() {
	var mqttClientId = "Spinning-Device-Test001"
	uri := &url.URL{
		Scheme: "tcp",
		Host:   fmt.Sprintf("%s:%d", brokerUrl, brokerPort),
		User:   url.UserPassword(username, password),
	}

	client, err := createMqttClient(mqttClientId, uri)
	if err != nil {
		fmt.Println(err)
	}

	defer client.Disconnect(5000)

	var qos = byte(0)
	var data = [frameLen]byte{}

	var tid uint64 = 1686122972408
	var spindle uint16 = 89
	frame_id := uint16(0xF5F5)
	data_len := uint16(3000*2 + 10)

	data[0] = byte(frame_id)
	data[1] = byte(frame_id >> 8)

	data[2] = byte(data_len)
	data[3] = byte(data_len >> 8)

	data[4] = byte(spindle)
	data[5] = byte(spindle >> 8)

	data[6] = byte(tid)
	data[7] = byte(tid >> 8)
	data[8] = byte(tid >> 16)
	data[9] = byte(tid >> 24)
	data[10] = byte(tid >> 32)
	data[11] = byte(tid >> 40)
	data[12] = byte(tid >> 48)
	data[13] = byte(tid >> 56)

	//var tmp, t2, t3, t4 uint16 = 0, 0, 0, 0
	var tmp uint16 = 0
	//var voltages = [6000]byte{}
	for i := 14; i < frameLen; i += 2 {

		tmp = uint16(rand.Uint32())
		data[i] = byte(tmp >> 8)
		data[i+1] = byte(tmp)
		// t2 = uint16(voltages[i*2]) << 8
		// t3 = uint16(voltages[i*2+1])
		// t4 = t2 + t3
		// fmt.Println(tmp, t4)
	}

	for {
		//jsonData, err := json.Marshal(data)
		if err != nil {
			fmt.Println(err)
		}
		//token := client.Publish(topicVoltages, qos, false, jsonData)

		token := client.Publish(topicVoltages, qos, false, data[:])
		fmt.Printf("### data.Voltages: \n %v ###\n", data)
		//fmt.Printf("### device client.Publish: \n %v ###\n", voltages)

		if token.Wait() && token.Error() != nil {
			fmt.Println(token.Error())
		}

		time.Sleep(time.Second * time.Duration(30))
	}

}

func createMqttClient(clientID string, uri *url.URL) (mqtt.Client, error) {
	fmt.Printf("### Create MQTT client and connection: uri=%v clientID=%v ###\n", uri.String(), clientID)
	opts := mqtt.NewClientOptions()
	opts.AddBroker(fmt.Sprintf("%s://%s", uri.Scheme, uri.Host))
	opts.SetClientID(clientID)
	opts.SetUsername(uri.User.Username())
	password, _ := uri.User.Password()
	opts.SetPassword(password)
	opts.SetConnectionLostHandler(func(client mqtt.Client, e error) {
		fmt.Printf("Connection lost : %v", e)
		token := client.Connect()
		if token.Wait() && token.Error() != nil {
			fmt.Printf("Reconnection failed : %v", e)
		} else {
			fmt.Printf("Reconnection sucessful : %v", e)
		}
	})

	client := mqtt.NewClient(opts)
	fmt.Println("### createMqttClient ###")
	token := client.Connect()
	if token.Wait() && token.Error() != nil {
		return client, token.Error()
	}

	return client, nil
}
